W5500 EVB使用主动模式与网络中的FTP服务器进行指令和数据的交互,所以,必须创建两个TCP的socket。一个TCP请求用于会话通道创建,另一个用于数据通道创建。遵循下面的程序来建立FTP客户端�
完成以上流程,有两个主要的函数:ftp_client_PI()和ftp_client_DTP(),第一个函数负责指令传输,第二个负责数据传输�
下面我们看一下程序上的实�void ftp_client_PI (uint8 sock) { int len; int idx; char msg[STR_SIZE]; uint16 status; static uint16 any_port =50000; memset(cmd_buf,0,sizeof(cmd_buf)); switch(getSn_SR(sock)) /*获取socket的状�*/ { case SOCK_INIT: /*socket初始化完�*/ if( connect(sock, FTP_SERVER_IP ,FTP_Server_CMD_Port)==0) printf("< Fail : Socket Connect >\r\n"); break; case SOCK_ESTABLISHED: /*socket连接建立*/ if(getSn_IR(sock)& Sn_IR_CON) { setSn_IR(sock, Sn_IR_CON); /*Sn_IR的第0位置1*/ } len=getSn_RX_RSR(sock); /*len为已接收数据的大�*/ if(len>0) { recv(sock,cmd_buf,len); /*W5500接收来自SeverServer的数�*/ for( idx=0; idx < len; idx++) { if( idx ==0) printf("\r\n"); printf("%c",cmd_buf[idx]); } switch( status = Parse_FTPServer_Statuscode(cmd_buf)) { case R_220: // 新用户服务已就绪Service ready for new user. printf("\r\nInput your User ID > "); GetInputString(msg); Send_USER_ID(sock,msg); break; case R_331: // 用户名字已验证,需要密� printf("\r\nInput your Password > "); GetInputString(msg); Send_PW(sock,msg); break; case R_230: //User logged in, proceed用户已登陆,处理� printf("\r\nUser logged in, proceed"); close(FTP_CLIENT_DTP_SOCK); Send_Port(sock, IP, DTP_Port); break; case R_200: //'Generic' command ok命令正确 printf("\r\nInput FTP CMD > "); GetInputString(msg); Send_cmd(sock, msg); break; case R_150: //File Status文件状态正确:打开数据链接 bRunDTP =1; break; case R_250: close(FTP_CLIENT_DTP_SOCK); Send_Port(sock, IP, DTP_Port); break; /* Closing data connection关闭数据链接. File transfer/abort successful ,文件传输终�/完成*/ case R_226: close(FTP_CLIENT_DTP_SOCK); Send_Port(sock, IP, DTP_Port); break; case R_425: close(FTP_CLIENT_DTP_SOCK); Send_Port(sock, IP, DTP_Port); break; default: printf("\r\nDefault Status = %d",(uint16)status); JumpAddress =*(volatileunsignedlong*)(ApplicationAddress +4);//复位程序reset app Jump_To_Application =(pFunction) JumpAddress; Jump_To_Application(); while(1); } } break; case SOCK_CLOSE_WAIT: /*socket等待关闭状�*/ break; case SOCK_CLOSED: /*socket关闭*/ printf("\r\n%d : FTP Client Start.\r\n",(u16)sock); socket(sock,Sn_MR_TCP,any_port++,Sn_MR_ND); /*初始化TCP socket*/ break; } }
上面的程序是FTP客户端会话通道的程序,在客户端与FTP成功连接后,会收到FTP服务器发来的220响应码,表示服务器已经准备就绪,可以接受用户登录。在使用Send_USER_ID() 和Send_PW()函数执行完登录流程后,FTP客户端使用Send_Port()主动向服务器发送自己的数据通道的端口号。最后等待用户的FTP指令,并使用Send_cmd()函数执行相应指令�
void ftp_client_DTP(uint8 sock) { int len; int idx; switch(getSn_SR(sock)) /*获取socket的状�*/ { case SOCK_INIT: listen(sock); bRunDTP =1; break; case SOCK_ESTABLISHED: if(getSn_IR(sock)& Sn_IR_CON) { setSn_IR(sock, Sn_IR_CON); /*Sn_IR的第0位置�1*/ } len=getSn_RX_RSR(sock); /*len为已接收数据的大�*/ if(len>0) { recv(sock,data_buf,len); /*W5500接收来自SeverServer的数�*/ for( idx =0; idx < len; idx++) { if( idx ==0) printf("\r\n"); printf("%c",data_buf[idx]); } } if(bRunDTP) { bRunDTP =0; #ifdef Debug printf("< FTP_DTP Connect OK>\r\n"); #endif } if( bRunPutFile ) { bRunPutFile =0; send(sock,(void*)PUTFILE, strlen(PUTFILE)); close(sock); } break; case SOCK_CLOSE_WAIT: /*防止对方关闭连接,而数据还未接收完*/ len=getSn_RX_RSR(sock); /*len为已接收数据的大�*/ if(len>0) { recv(sock,data_buf,len); /*W5500接收来自Server的数�*/ for( idx =0; idx < len; idx++ { if( idx ==0) printf("\r\n"); printf("%c",data_buf[idx]); } } if( bRunPutFile ) { bRunPutFile =0; send(sock,(void*)PUTFILE, strlen(PUTFILE)); } close(sock); break; case SOCK_CLOSED: socket(sock,Sn_MR_TCP,DTP_Port++,Sn_MR_ND); if( DTP_Port >70000) DTP_Port = FTP_Client_TCPS_Port; break; } }
上面的程序是FTP客户端的数据通道程序,该socket一直监听,等待FTP服务器的连接。如果接到数据,会通过串口打印出来,如果有发送请求,将测试字符串发送给服务器。在完成下载安装后, 我们添加一个账户(本节使用的账户是wiznet,密�123456),并为这个账户添加一个文件夹,并勾选文件所有操作。点击确定后,这个账户就可以被连接了。如�1�3所示�